package com.szeldon.declatest.eval.plugins;

import java.io.StringBufferInputStream;
import java.util.Properties;
import java.util.logging.Logger;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.xml.sax.InputSource;

import com.szeldon.declatest.eval.IScenarioEvaluatorPlugin;
import com.szeldon.declatest.eval.exceptions.EvaluationException;
import com.szeldon.declatest.exec.AbstractTestsSuiteExecutor;
import com.szeldon.declatest.exec.TestSuiteExecHistory;

/**
 * Evaluator plugin for XPath (currently only XPath 1.0 is supported).
 * 
 * @author szeldon
 * 
 */
public class XPathEvaluatorPlugin implements IScenarioEvaluatorPlugin {

    public static final String XPATH_EVALUATOR_PLUGIN_PREFIX = "xpath";

    public static final String SEPARATOR = "@";

    private static Logger logger = Logger.getLogger(XPathEvaluatorPlugin.class.getName());

    @Override
    public boolean evaluateOperator(AbstractTestsSuiteExecutor executor, String leftValue, String operator,
            String rightValue, Properties properties, TestSuiteExecHistory history) {
        throw new UnsupportedOperationException(XPathEvaluatorPlugin.class
                + " doesn't support  evaluation of operators.");
    }

    @Override
    public String evaluateValue(AbstractTestsSuiteExecutor executor, String value, Properties properties,
            TestSuiteExecHistory history) throws EvaluationException {

        logger.fine("Evaluating XPath value=" + value);

        String result = null;

        int separatorIndex = value.lastIndexOf(SEPARATOR);
        if (separatorIndex == -1) {
            throw new EvaluationException("Can't use XPath plugin on a value without '" + SEPARATOR + "' separator.");
        }

        // extracts XPath expression and content on which this expression will be evaluated
        String xpathExpressionString = value.substring(0, separatorIndex);
        String content = value.substring(separatorIndex + 1);

        try {

            // xpath starts here
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath xpath = xpathFactory.newXPath();
            // FIXME: change to other input stream class, because StringBufferInputStream is deprecated
            result = xpath.evaluate(xpathExpressionString, new InputSource(new StringBufferInputStream(content)));

        } catch (XPathExpressionException e) {
            throw new EvaluationException("Can't evaluate XPath expression. " + e.getCause().getMessage(), e);
        }

        logger.fine("Evaluated XPath: " + result);

        return result;
    }

    @Override
    public String getPluginPrefix() {
        return XPATH_EVALUATOR_PLUGIN_PREFIX;
    }

}
